const crypto = require('crypto')
const CryptoJS = require('crypto-js')
const { app } = require('electron')
const path = require('path')
const fs = require('fs')

/**
 * 安全密钥管理器
 * 提供数据库加密密钥的生成、存储和获取功能
 */
class KeyManager {
  constructor() {
    // 基于应用信息生成的固定种子
    this.baseSeed = this.generateBaseSeed()
    
    // 混淆密钥存储路径
    this.keyPath = this.getKeyStoragePath()
  }

  /**
   * 生成基础种子
   * 基于应用的固定信息生成，确保在同一设备上的一致性
   */
  generateBaseSeed() {
    const appInfo = {
      name: 'electron-vite-knex-sqlite3',
      version: '1.0.0',
      // 使用系统信息作为额外的熵源
      platform: process.platform,
      arch: process.arch,
      // 使用用户目录作为设备特定标识
      userHome: require('os').homedir()
    }
    
    const baseString = JSON.stringify(appInfo)
    return crypto.createHash('sha256').update(baseString).digest('hex')
  }

  /**
   * 获取密钥存储路径
   */
  getKeyStoragePath() {
    const userDataPath = app ? app.getPath('userData') : path.join(__dirname, '..', '..')
    const configDir = path.join(userDataPath, '.config')
    
    // 确保配置目录存在
    if (!fs.existsSync(configDir)) {
      fs.mkdirSync(configDir, { recursive: true })
    }
    
    return path.join(configDir, '.app_config')
  }

  /**
   * 生成数据库加密密钥
   * 使用多层混淆策略
   */
  generateDatabaseKey() {
    // 第一层：基于基础种子生成
    const primaryKey = crypto.createHmac('sha256', this.baseSeed)
      .update('database_encryption_key')
      .digest('hex')

    // 第二层：时间戳混淆（基于安装时间或首次运行时间）
    const installTime = this.getInstallTimestamp()
    const timeKey = crypto.createHmac('sha256', primaryKey)
      .update(installTime.toString())
      .digest('hex')

    // 第三层：环境混淆
    const environment = this.getEnvironmentHash()
    const finalKey = crypto.createHmac('sha256', timeKey)
      .update(environment)
      .digest('hex')

    // 返回适合SQLCipher的密钥（64字符十六进制）
    return finalKey.substring(0, 64)
  }

  /**
   * 获取安装时间戳
   * 如果不存在则创建一个
   */
  getInstallTimestamp() {
    try {
      if (fs.existsSync(this.keyPath)) {
        console.log("this.keyPath", this.keyPath)
        const encryptedData = fs.readFileSync(this.keyPath, 'utf8')
        const decryptedData = this.deobfuscateData(encryptedData)
        
        if (decryptedData) {
          const config = JSON.parse(decryptedData)
          if (config.timestamp) {
            return config.timestamp
          }
        }
      }
    } catch (error) {
      console.warn('读取安装时间戳失败:', error.message)
    }

    // 生成新的时间戳
    const timestamp = Date.now()
    this.saveTimestamp(timestamp)
    return timestamp
  }

  /**
   * 保存时间戳
   */
  saveTimestamp(timestamp) {
    try {
      const config = { timestamp }
      // 使用混淆存储
      const obfuscatedConfig = this.obfuscateData(JSON.stringify(config))
      fs.writeFileSync(this.keyPath, obfuscatedConfig, 'utf8')
    } catch (error) {
      console.warn('保存时间戳失败:', error.message)
    }
  }

  /**
   * 获取环境哈希
   */
  getEnvironmentHash() {
    const envInfo = {
      nodeVersion: process.version,
      execPath: process.execPath,
      // 使用部分系统信息，避免过于敏感
      platform: process.platform,
      arch: process.arch
    }
    
    return crypto.createHash('md5')
      .update(JSON.stringify(envInfo))
      .digest('hex')
  }

  /**
   * 数据混淆
   */
  obfuscateData(data) {
    const key = this.baseSeed.substring(0, 32)
    return CryptoJS.AES.encrypt(data, key).toString()
  }

  /**
   * 数据反混淆
   */
  deobfuscateData(encryptedData) {
    try {
      const key = this.baseSeed.substring(0, 32)
      const bytes = CryptoJS.AES.decrypt(encryptedData, key)
      return bytes.toString(CryptoJS.enc.Utf8)
    } catch (error) {
      console.warn('数据反混淆失败:', error.message)
      return null
    }
  }

  /**
   * 获取数据库密钥
   * 主要对外接口
   */
  getDatabaseKey() {
    try {
      return this.generateDatabaseKey()
    } catch (error) {
      console.error('生成数据库密钥失败:', error)
      // 返回一个基于基础种子的简化密钥作为后备方案
      return crypto.createHash('sha256').update(this.baseSeed).digest('hex').substring(0, 64)
    }
  }

  /**
   * 验证密钥是否有效
   */
  validateKey(key) {
    return typeof key === 'string' && key.length === 64 && /^[a-f0-9]+$/i.test(key)
  }

  /**
   * 清除存储的配置（用于重置）
   */
  clearConfig() {
    try {
      if (fs.existsSync(this.keyPath)) {
        fs.unlinkSync(this.keyPath)
        console.log('密钥配置已清除')
      }
    } catch (error) {
      console.warn('清除密钥配置失败:', error.message)
    }
  }
}

module.exports = KeyManager